#!/usr/bin/env python

#################################################################################
#
# Copyright (c) 2006 Michigan State University
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#################################################################################

#################################################################################
#
#	Author:
#		Nathan Collins <npcollins@gmail.com>
#
#################################################################################

from terms import terms_handler, webs, urls, boldify
from dbinter import err_exit, oai_db, make_hash
from output import shorten, output
from datetime import datetime
from PyLucene import *
from oaicookie import *
from oaisimilarity import *
import cgi

# the searcher class
class searcher:
	def __init__(self):
		# directory of index data
		self.index_dir = '/var/oai'
		
		# max results to return at a time
		self.max_result = 20
		
		self.connect()

	def connect(self):
		self.searcher = IndexSearcher(self.index_dir)
		self.searcher.setSimilarity(oaiSimilarity())

	def process_search(self,search,loc,within,expand):
		self.loc = int(loc)

		if self.loc > 981:
			print "Content-type:  text/plain\n"
			print "Only the first 1000 results are available for viewing. Please refine your terms and seach again."
			return 0
		
		self.terms = search
		th = terms_handler(self.terms)
		self.termlist = th.get_terms()

		parser = QueryParser("keywords", StandardAnalyzer())
		#parser.setOperator(QueryParser.DEFAULT_OPERATOR_AND)
		# parse query
		try:
			query = parser.parse(th.get_query())
		except:
			# search failed, likely invalid, try a safe search
			try:
				using_safe = 1
				query = parser.parse(th.get_query_safe())
			except:
				# catch bad syntax
				print 'Content-type: text/plain\n'
				print 'Invalid search. A more friendly response to this error is being worked on.'
				return 0
		boolQuery = BooleanQuery()
		boolQuery.add(query, BooleanClause.Occur.MUST)
		# searching within a previous search
		if len(within.strip()) > 1:
			thw = terms_handler(within)
			origQuery = parser.parseQuery(thw.get_query())
			boolQuery.add(origQuery, BooleanClause.Occur.MUST)
			
		start = datetime.now()
		hits = self.searcher.search(boolQuery)
		duration = datetime.now() - start

		# trim off hours and minutes
		duration = str(duration).split(':')[2][0:6]
		self.total_results = len(hits)

		# end of result for this page
		result_end = min(len(hits),self.loc + self.max_result - 1)

		# begin generating output
		pageOut = output(self.total_results,self.loc,self.max_result,self.terms,self.termlist)

		# cookies
		addCookieList('searchHistory',self.terms)
		# page
		print "Content-type: text/html; charset=utf-8\n"
		pageOut.header()
		pageOut.search_bar()
		pageOut.searchSubHeader()
		pageOut.print_result_bar(result_end, duration)

		# current record
		cur = 1

		for i, doc in hits:
			if cur >= self.loc and cur <= result_end:
				# load record fields into dict
				table = dict([(field.name(),field.stringValue()) for field in doc])
				# escape unicode
				table = dict([(key,webs(table[key])) for key in table])
				
				# dev score
				#print '<b>Score: %s</b>' % hits.score(cur-1)

				pageOut.print_rec(table, expand)
			if cur >= result_end:
				# the last record we sent
				self.last = cur
				# finish output
				break
			cur += 1

		pageOut.footer(within)
		return


# main function
class main:
	def __init__(self):
		# string to return
		self.data = ''
		self.params = cgi.FieldStorage()
		try:
			self.search = self.params['s'].value
		except:
			# catch nasties
			print "Content-type: text/plain\n"
			print """
			Invalid search or error. Please report this error to the page maintainer
			with exact details of what and how you were searching. This will help us
			to identify the bug you experianced and resolve it. Thank you."""
		try:
			self.location = self.params['l'].value
		except:
			self.location = 1
		try:
			self.within = self.params['w'].value
		except:
			self.within = ''
		try:
			self.expand = self.params['e'].value
		except:
			self.expand = ''

		# connect to the database
#		self.db = oai_db()
#		self.db.connect()

		# connect to lucene
		self.luc = searcher()
		self.luc.connect()

	def finish(self):
		# disconnect from the db
#		self.db.disconnect()
		pass

	def process(self):
		# make the page
		self.luc.process_search(self.search,self.location,self.within,self.expand)

# begin execution
def search():
	page = main()
	data = page.process()

if __name__ == '__main__' or __name__ == 'search':
	search()

#eof

